import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;

/**
 * @author xhw
 */

public class String类的常用方法 {
    public static void main(String[] args) {
        //使用+连接字符串 TODO说明不同方法的差异
        //使用”+“连接字符其实时在内部通过创建了StringBuilder对象来实现的，每次连接两个字符串实际上会生成一个新的字符串对象，这是因为String时不可变的
        String str1 = "hello";
        String str2 = "world";
        String str3 = str1 + " " + str2; // 结果是 "hello world"

        //对于大量字符串拼接，建议使用StringBuilder类来提高性能
        //这是因为使用”+“虽然也是创建StringBuilder对象来完成但是如果数量很多，那么就会创建很多个，不断的增加多余的对象，而StringBuilder提供的
        //append方法使得整个拼接过程只创建一个对象，当大量字符串拼接的时候性能比”+“更高
        StringBuilder sb = new StringBuilder();
        String str4 = sb.append(str1).append(" ").append(str2).toString(); // 结果是 "hello world"

        //String.join，join方法是Java 8引入的，可用于连接具有分隔符的多个字符串。
        //这个方法是接受一个分隔符和一个字符串，每个元素之间用分隔符隔开，在内部也是使用了StringBuilder一次性完成
        final String join = String.join("|", str1, str2, str1); // 结果是 "hello|world|hello"

        //TODO解释乱码
        //数据的存储和传输都是以二进制的形式进行的，而二进制数据是无法直接显示的，所以需要将二进制数据转换为人类可读的字符，这个过程就是编码。
        //而当存储的编码方式例如（UTF_8）但是在读取的时候使用了另外一种编码方式的时候例如（ISO-8859-1）的时候那么就会导致乱码，要避免乱码就要
        //保证编码方式一致

        //字符串序列化与反序列化
        // 字符串的序列化即按一定的编码规则，将字符串转换为二进制数据。
        //字符串的反序列化即按一定的编码规则，将二进制数据恢复为字符串。
        String str = "hello world,你好 ";
        final byte[] utf_8_data = str.getBytes(StandardCharsets.UTF_8);
        byte[] bytes = str.getBytes();
        final byte[] ISO_8859_1_data = str.getBytes(StandardCharsets.ISO_8859_1);

        final String s1 = new String(utf_8_data, StandardCharsets.UTF_8);
        final String s2 = new String(utf_8_data, StandardCharsets.ISO_8859_1);

        //大小写转换与去除空白
        String str5 = "Hello world,你好";
        String upperCase = str.toUpperCase(); // 结果是 "HELLO WORLD,你好"
        String lowerCase = str.toLowerCase(); // 结果是 "hello world,你好"

        String trimmed = str.trim(); // 如果str前后有空格，trim()将移除它们

        // 和长度有关的方法
        String example = "hello world,你好";
        int length = example.length();


        // 和判断有关的方法
        boolean equals = example.equals("hello world,你好");
        boolean equalsIgnoreCase = example.equalsIgnoreCase("HELLO WORLD,你好");
        boolean contains = example.contains("world");
        boolean startsWith = example.startsWith("hello");
        boolean endsWith = example.endsWith("你好");

        // 和改变内容有关的方法
        String replace = example.replace("world", "everyone");
        String replaceAll = example.replaceAll("你好", "大家好");
        String replaceFirst = example.replaceFirst("l", "L");
        String substring = example.substring(6);
        String sub = example.substring(0, example.indexOf(","));
        String trim = "   hello   ".trim();

        //replace、replaceAll、replaceFirst的区别
        //replace：替换新旧字符
        String str6 = "hello world,你好 ";
        str6 = str6.replace("world", "java");
        //replaceAll：也是替换但是使用的是正则表达式匹配，满足则会替换所有正则表达式匹配的部分，
        //例如这段代码匹配的就是所有的数字，那么就会修改两个“123”改为“java”
        String s = "hello123 world123";
        s = s.replaceAll("\\d+", "java");

        // 和位置有关的方法
        char charAt = example.charAt(1);
        int indexOf = example.indexOf("world");
        int lastIndexOf = example.lastIndexOf("你好");

        //分隔方法
        //这里的参入的匹配可以是正则表达式然后返回一个字符窜数组，包含被分割的各个类型
        String[] split = example.split(" ");
        String[] split1 = example.split(" ", 2);


        //格式化字符串

        //占位符写法，会按照参数顺序被替换
        "my name is %s".formatted("Tom"); // 结果是 "my name is Tom"
        //创建一个格式化的字符串，原理同上，但是不局限于插入一个单词，还
        String.format("my name is %s", "Tom"); // 结果是 "my name is Tom"
        //效果同上，但是可以插入多个单词，插入的位置由占位符决定
        MessageFormat.format("my name is {0}", "Tom"); // 结果是 "my name is Tom"

        //上面的知识是 “术”

        //TODO 说明：string是不可变的 这是知识是“道”

//        符合【一个底层逻辑】
//        1.按照这个逻辑，所以String不可变；
//        2.按照这个逻辑。。。。
    }
}
